package com.dingding.special.order.appoint.biz.special;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;

import com.dingding.common.core.beans.Userdetail;
import com.dingding.common.core.beans.special.UserspecialorderT;
import com.dingding.common.core.push.enums.push.SpecialDriverPushEnum;
import com.dingding.common.core.push.factory.dtos.OrderDurationDTO;
import com.dingding.common.core.push.factory.request.IPushRequestFactory;
import com.dingding.common.core.util.JSONUtil;
import com.dingding.common.core.util.amap.AmapApi;
import com.dingding.facade.queue.facade.IQueueFacade;
import com.dingding.special.order.appoint.biz.IAppointSpecialOrderService;
import com.dingding.special.order.appoint.cache.AppointOrderCache;
import com.dingding.special.order.appoint.dao.IAppointDao;
import com.dingding.special.order.grab.dto.ReqUserGrabDTO;
import com.dingding.special.order.grab.service.IUserGrabService;
import com.dingding.special.user.customer.dao.ICustomerUserDao;
import com.dingding.special.user.driver.dao.IDriverUserDao;
import com.dingding.special.user.driver.dto.onlinedriver.OLineDriverDto;

/**
 * @Description:指派实时订单的处理类
 * @author fengshuonan
 * @date 2016年8月23日 下午4:29:28
 * @version 叮叮搭车
 * @since 2.4
 */
@Component("appointRealOrderService")
public class AppointRealOrderServiceImpl implements IAppointSpecialOrderService{
	
	private Logger log = Logger.getLogger(this.getClass());

	@Resource(name = "driverUserDao")
	private IDriverUserDao driverUserDao;
	
	@Resource(name = "customerUserDao")
	private ICustomerUserDao customerUserDao;
	
	@Resource(name = "specialDriverPushRequestFactory")
	private IPushRequestFactory specialDriverPushRequestFactory;
	
	@Resource(name = "customerPushRequest")
	private IPushRequestFactory customerPushRequest;
	
	@Resource(name = "queueFacade")
	private IQueueFacade queueFacade;
	
	@Resource(name = "appointDao")
	private IAppointDao appointDao;
	
	@Resource(name = "userGrabService")
	private IUserGrabService userGrabService;
	
	@Override
	public boolean appointSpecialOrder(UserspecialorderT userspecialorderT) {
		
		log.error(JSONUtil.toJSONString(userspecialorderT));
		
		//如果该订单不存在或者不是待指派状态，则返回成功，不让队列里继续存在
		if(appointDao.getSpecialOrderStatus(userspecialorderT.getSpecialOrderId()) != 1){
			log.error("如果该订单不存在或者不是待指派状态，则返回成功，不让队列里继续存在！orderId:" + userspecialorderT.getSpecialOrderId() + "orderStatus:" + appointDao.getSpecialOrderStatus(userspecialorderT.getSpecialOrderId()));
			AppointOrderCache.deleteRedisOrder(userspecialorderT);
			return true;
		}
		
		//获取偏好为实时订单的所有在线司机
		List<OLineDriverDto> list = this.driverUserDao.getRealTimeOnlineDrivers(userspecialorderT.getPlaceOrderCity());
		
		Collections.shuffle(list);
		
		log.error("在线司机： " + list.size());
		
		//判断此订单是否和在线车主所匹配
		for(OLineDriverDto dto : list){
			boolean flag = this.isMacthing(userspecialorderT, dto);
			
			//如果订单与司机的条件相匹配，则推送给司机这个单
			if(flag == true){
				
				/**
				 * 判断司机近期30秒之内有没有被指派过订单
				 * 如果被指派过,则略过此人
				 */
				if(AppointOrderCache.haveAppointedRecently(dto.getUserId(),userspecialorderT.getSpecialOrderId())){
					continue;
				}
				
				//获取乘客的详情
				Userdetail userdetail = this.customerUserDao.getUserdetail(userspecialorderT.getPlaceOrderUserId());
				
				// 乘客与司机不能是同一个人(防止刷单)
				if(dto.getTelPhone().equals(userdetail.getTellphone())){
					continue;
				}
				
				//获取订单的里程信息
				OrderDurationDTO orderDurationDTO = this.appointDao.getOrderDuration(dto,userspecialorderT);
				
				userspecialorderT.setOrderStatus(2);//1:待指派  2:待上车(已指派)  3:已上车  4:待支付(已到达)  5:已完成  6:已取消
				
				//推送该订单给司机
				pushDriverOrder(userspecialorderT, dto, userdetail, orderDurationDTO);
				
				//添加该订单的司机信息
				this.appointDao.afterPushToDriver(userspecialorderT.getSpecialOrderId(),dto.getUserId());
				
				//推送给乘客信息
				userGrabService.grabPush(new ReqUserGrabDTO(userspecialorderT.getSpecialOrderId(),
						dto.getUserId()));
				
				// 推送给乘客通知内容
				userGrabService.grabPushNotice(new ReqUserGrabDTO(userspecialorderT.getSpecialOrderId(),
						dto.getUserId()));
				
				return true;
			}
		}
		return false;
	}

	/**
	 * @Description 发送指派订单的推送给司机
	 * @param userspecialorderT 专车订单临时表中的订单
	 * @param dto 在线司机的详细信息封装
	 * @param userdetail 乘客的用户详情
	 * @param orderDurationDTO 订单历程信息的封装
	 * @author fengshuonan
	 */
	protected void pushDriverOrder(UserspecialorderT userspecialorderT, OLineDriverDto dto, Userdetail userdetail,
			OrderDurationDTO orderDurationDTO) {
		String pushBean = this.specialDriverPushRequestFactory.createPushRequestString(
				SpecialDriverPushEnum.AppointSpecialOrderPush.toString(),
				dto.getUserId(),userdetail, userspecialorderT,orderDurationDTO);
		this.queueFacade.addPushToQueue(pushBean);
	}

	/**
	 * @modify by hufan 新添加约束条件（车辆等级）
	 */
	@Override
	public boolean isMacthing(UserspecialorderT userspecialorderT, OLineDriverDto oLineDriverDto) {
		
		//添加司机车辆类型( 1: 经济型 2：舒适型) 是否符合订单要求
		if(userspecialorderT.getVehicleLevelId() != oLineDriverDto.getVehicleLevelId()) {
			return false;
		}
		
		//判断司机是否有进心中的实时订单
		boolean haveOrders = this.appointDao.isDriverOrdering(oLineDriverDto.getUserId());
		
		//如果有进行中订单，则不给司机匹配这个单
		if(haveOrders == true){
			log.error("司机有进行中订单！" + oLineDriverDto.getUserId());
			return false;
		}
		
		double startLng = userspecialorderT.getStartLongitude();
		double startlat =  userspecialorderT.getStartLatitude();
		double driverLng = oLineDriverDto.getLongitude();
		double driverlat = oLineDriverDto.getLatitude();
		
		BigDecimal distance = new BigDecimal(0);
		try {
			distance = AmapApi.getTwoPointDistance(startLng, startlat, driverLng, driverlat);
		} catch (Exception e) {
			log.error("获取两点之间的距离出错！AppointRealOrderServiceImpl : isMacthing()",e);
			return false;
		}
		
		//如果乘客和司机距离小于司机的偏好距离
		if(distance.compareTo(oLineDriverDto.getDistanceFilter()) < 0){
			return true;
		}else{
			log.error("偏好距离错误！" + oLineDriverDto.getUserId());
			return false;
		}
	}
}